package serv

import (
	bean "d-serv-go/server/core/bean"
	"d-serv-go/server/core/cache"
	"d-serv-go/server/core/consts"
	"d-serv-go/server/core/db"
	"d-serv-go/server/core/log"
	"d-serv-go/server/core/util"
	strutils "d-serv-go/server/core/util/stringutils"
	"errors"
	"github.com/kirinlabs/utils/str"
)

var ServUtils = newServUtils()

type servUtils struct {
}

func newServUtils() *servUtils {
	return &servUtils{}
}

func (u *servUtils) GetServBean(servId string) (*ServBean, error) {
	if str.Length(servId) == 0 {
		return nil, errors.New("服务编码不可以为空")
	}
	val := cache.CacheMgr.Get(servId, consts.CACHE_TYPE_SERV)
	if val != nil {
		return val.(*ServBean), nil
	}
	// 获取服务的json
	servJson, err := db.ServMgr.GetServJson(servId)
	if err != nil {
		return nil, err
	}
	m, err := servJson.Map()
	serv := NewServBean2(m)
	// TODO $ITEMS $ITEMS_TABLE 等属性的构建
	itemsBean := bean.NewBean("")
	tableItems := []*bean.Bean{}
	viewItems := []*bean.Bean{}
	combineItems := []*bean.Bean{}
	uniqueMap := bean.NewBean("")
	bFirst := true
	for _, item := range servJson.Get(consts.TABLE_SERV_ITEM).MustArray() {
		if m2, ok := item.(map[string]interface{}); ok {
			itemBean := bean.NewBean2(m2)
			if itemBean.GetInt("S_FLAG") != consts.YES_INT { // 忽略无效字段
				continue
			}
			isKey := false
			if itemBean.GetInt("ITEM_TYPE", consts.ITEM_TYPE_TABLE) == consts.ITEM_TYPE_TABLE {
				if serv.GetPKey() == itemBean.GetStr("ITEM_CODE") {
					isKey = true
				} else if bFirst && serv.IsEmpty("SERV_KEYS") { // 如果没有主键自动用第一个字段为主键
					serv.Set("SERV_KEYS", itemBean.GetStr("ITEM_CODE"))
					isKey = true
				}
				if itemBean.GetInt("ITEM_LOG_FLAG") == consts.YES_INT { // 启用留痕
					serv.Set(consts.ITEM_LOG_FLAG, consts.YES_INT)
				}
				if itemBean.GetInt("ITEM_UNIQUE_GROUP") > 0 { // 设定了唯一分组
					uList := uniqueMap.GetArray(itemBean.GetStr("ITEM_UNIQUE_GROUP"))
					if uList == nil {
						uList = []interface{}{}
						uniqueMap.Set(itemBean.GetStr("ITEM_UNIQUE_GROUP"), uList)
					}
					uList = append([]interface{}{itemBean.Get("ITEM_CODE")}, uList...)
				}
				if (itemBean.GetInt("ITEM_INPUT_MODE") == consts.ITEM_INPUT_MODE_COMBINE) {
					combineItems = append(combineItems, itemBean)
				}
				//if (itemBean.getInt("ITEM_INPUT_TYPE") == ServConstant.ITEM_INPUT_TYPE_FILE) { // 文件上传字段
				//	fileFieldItems.add(itemBean);
				//}
				if isKey { // 将主键放在第一个位置
					tableItems = append([]*bean.Bean{itemBean}, tableItems...)
					viewItems = append([]*bean.Bean{itemBean}, viewItems...)
				} else {
					tableItems = append(tableItems, itemBean)
					viewItems = append(viewItems, itemBean)
				}
			} else if itemBean.GetInt("ITEM_TYPE") == consts.ITEM_TYPE_VIEW {
				if (itemBean.GetInt("ITEM_INPUT_MODE") == consts.ITEM_INPUT_MODE_COMBINE) {
					combineItems = append(combineItems, itemBean)
				}
				viewItems = append(viewItems, itemBean)
			}
			/*else { // 自定义类型
				if (itemBean.GetInt("ITEM_INPUT_TYPE") == constant.ITEM_INPUT_TYPE_RELATE) { // 相关数据
					String relateConfig = itemBean.GetStr("ITEM_INPUT_CONFIG");
					if (relateConfig.length() > 0) {
						List<String> relateIds = servDef.getList("SERV_RELATE_IDS");
						List<Bean> relateList = JsonUtils.toBeanList(relateConfig);
						for (Bean relate : relateList) {
							relateIds.add(relate.getStr("servId"));
						}
						servDef.set("SERV_RELATE_IDS", relateIds);
					}
				} else if (itemBean.getInt("ITEM_INPUT_TYPE") == ServConstant.ITEM_INPUT_TYPE_LABEL) { // 自定label
					if (itemBean.getStr("ITEM_CODE").startsWith("_MIND_")) { // 启用了意见label展示
						servDef.set("SERV_MIND_LABLE_FLAG", true); // 设置意见label展示标志
					}
				} else if (itemBean.getInt("ITEM_INPUT_TYPE") == ServConstant.ITEM_INPUT_TYPE_ATTACHMENT) {
					fileSelfItems.add(itemBean);
				} else if (itemBean.getInt("ITEM_INPUT_TYPE") == ServConstant.ITEM_INPUT_TYPE_COMMENT) { // 启用了评论功能
					servDef.set("SERV_COMMENT_FLAG", Constant.YES); // 系统启用了评论服务
				}
			}
			if (fileFieldItems.size() > 0 || fileFieldItems.size() > 0) { // 包含文件处理，设置文件标志
				servDef.set("SERV_FILE_FLAG", Constant.YES);
			}*/
			if bFirst { // 第一行规则处理
				bFirst = false
			}

			itemsBean.Set(itemBean.GetStr("ITEM_CODE"), itemBean)
		}
	}
	actsBean := bean.NewBean("")
	for _, item := range servJson.Get(consts.TABLE_SERV_ACT).MustArray() {
		if m2, ok := item.(map[string]interface{}); ok {
			actBean := bean.NewBean2(m2)
			if actBean.GetInt("S_FLAG") == consts.YES_INT {
				actsBean.Set(actBean.GetStr("ACT_CODE"), actBean)
			}
		}
	}

	linksBean := bean.NewBean("")
	for _, item := range servJson.Get(consts.TABLE_SERV_LINK).MustArray() {
		if m2, ok := item.(map[string]interface{}); ok {
			linkBean := bean.NewBean2(m2)
			if linkBean.GetInt("S_FLAG") == consts.YES_INT {
				linksBean.Set(linkBean.GetStr("LINK_SERV_ID"), linkBean)
			}
		}
	}

	if uniqueMap.Size() > 0 {
		serv.Set(consts.ITEM_UNIQUE_GROUP, uniqueMap)
	}
	serv.Set(consts.SERV_ID, servId)
	serv.Set(consts.ACTS, actsBean)
	serv.Set(consts.ITEMS, itemsBean)
	serv.Set(consts.LINKS, linksBean)
	serv.Set(consts.ITEMS_TABLE, tableItems) // 表对应字段列表
	serv.Set(consts.ITEMS_VIEW, viewItems)   // 表+视图对应字段列表
	serv.Set(consts.COMBINE_ITEMS, combineItems); // 组合值对应的字段
	serv.Set("SERV_INIT", true)
	cache.CacheMgr.Set(servId, serv, consts.CACHE_TYPE_SERV)
	log.Info("set serv to cache: ", servId)
	return serv, nil
}

func (u *servUtils) GetSearchWhere(serv *ServBean, getStr string) string {
	return ""
}

func (u *servUtils) ReplaceSysVars(src string) string {
	return db.VarMgr.ReplaceSysVar(src)
}

func (u *servUtils) ReplaceSysAndData(script string, dataBean *bean.Bean) string {
	return util.BeanUtil.ReplaceValues(u.ReplaceSysVars(script), dataBean)
}

func (u *servUtils) CheckUniqueExists(serv *ServBean, bean *bean.Bean, b bool) string {
	//String uniqueStr = null
	//HashMap<Object, List<String>> uniqueMap = serv.GetUniqueGroups();
	//if (uniqueMap != null) {
	//	StringBuilder sb = new StringBuilder(" and (");
	//	StringBuilder sbName = new StringBuilder("(");
	//	List<Object> params = new ArrayList<Object>();
	//	boolean first = true;
	//	for (Object key : uniqueMap.keySet()) {
	//		if (!first) {
	//			sb.append(" or ");
	//			sbName.append(" 或 ");
	//		} else {
	//			first = false;
	//		}
	//		sb.append("(");
	//		List<String> uList = uniqueMap.get(key);
	//		boolean bFirst = true;
	//		for (String code : uList) {
	//			if (!bFirst) {
	//				sb.append(" and ");
	//				sbName.append("、");
	//			} else {
	//				bFirst = false;
	//			}
	//			sb.append(code).append("=?");
	//			params.add(paramBean.get(code));
	//			Bean item = servDef.getItem(code);
	//			String value = paramBean.getStr(code);
	//			if (item.isNotEmpty("DICT_ID")) { // 字典项，动态处理名称
	//				value = DictMgr.getFullName(item.getStr("DICT_ID"), value);
	//			}
	//			sbName.append(servDef.getItemName(code)).append("=").append(value);
	//		}
	//		sb.append(")");
	//	}
	//	sbName.append(")");
	//	sb.append(")");
	//	if (!createFlag) { // 修改
	//		sb.append(" and ").append(servDef.getPKey()).append("!=?");
	//		params.add(paramBean.getId());
	//	}
	//	Bean queryBean = new Bean();
	//	queryBean.set(Constant.PARAM_WHERE, sb.toString());
	//	queryBean.set(Constant.PARAM_PRE_VALUES, params);
	//	if (ServDao.count(servDef.getId(), queryBean) > 0) {
	//		uniqueStr = sbName.toString();
	//	}
	//}
	//return uniqueStr;
	return ""
}

func (u *servUtils) GetLinkDataList(servId string, linkDef *bean.Bean, dataBean *bean.Bean, level int) []*bean.Bean {
	linkWhere := u.getLinkSql(servId, linkDef, dataBean, false)
	var dataList []*bean.Bean
	if len(linkWhere) > 0 { // 必须有过滤条件设定
		param := db.NewParamBean()
		// 设置where条件及级联参数（强制级联查询）
		param.Set(consts.PARAM_WHERE, linkWhere)
		param.SetLinkFlag(true)
		param.Set(consts.PARAM_LINK_LEVEL, level+1)
		param.SetServId(linkDef.GetStr("LINK_SERV_ID"))
		param.SetAct(consts.ACT_FINDS)

		outBean := db.ServMgr.Act(param)
		dataList = outBean.GetBeans(consts.RTN_DATA)
	} else {
		dataList = make([]*bean.Bean, 0)
	}
	return dataList
}

func (u *servUtils) getLinkSql(servId string, linkDef *bean.Bean, dataBean *bean.Bean, delFlag bool) string {
	where := strutils.NewStringBuilder()
	linkDefBean, _ := ServUtils.GetServBean(linkDef.GetStr("LINK_SERV_ID"))
	if delFlag && linkDefBean.HasFalseDelete() { // 子数据启用了假删除
		where.Append(" and S_FLAG=1")
	}
	if linkDef.GetInt("LINK_SHOW_TYPE") != consts.LINK_SHOW_TYPE_URL {
		where.Append(u.ReplaceSysAndData(linkDef.GetStr("LINK_WHERE"), dataBean)) // 特定where
	}

	param := bean.NewBean("")
	linkItems := linkDef.GetBeans("SY_SERV_LINK_ITEM")
	if linkItems == nil {
		return where.ToString()
	}
	for _, item := range linkItems {
		if item.GetInt("LINK_WHERE_FLAG") == consts.YES_INT { // 过滤条件
			if item.GetInt("LINK_VALUE_FLAG") == consts.YES_INT { // 字段传值
				param.Set(item.GetStr("LINK_ITEM_CODE"), dataBean.Get(item.GetStr("ITEM_CODE")))
			} else { // 传常量值
				param.Set(item.GetStr("LINK_ITEM_CODE"), item.Get("ITEM_CODE"))
			}
		}
	}
	where.Append(u.where(linkDef.GetStr("LINK_SERV_ID"), param)) // 增补上关联明细拼接的where
	return where.ToString()
}

func (u *servUtils) where(servId string, dataBean *bean.Bean) string {
	servDef, _ := u.GetServBean(servId)
	return SqlBuilder.Where(servDef, dataBean)
}

func (u *servUtils) GenCombineItem(id string, code string, getStr string, out *bean.OutBean) interface{} {
	// TODO

	return nil
}
//记录数据项变更历史
func (u *servUtils) ItemLog(list []*bean.Bean) {
	/*var sql string
	List<List<Object>> params = new ArrayList<List<Object>>(changeList.size());
	userInfo := db.Ctx().GetUserBean();
	tm := util.DateUtil.GetDatetimeTS();
	for (Bean data : changeList) {
		data.set("ILOG_ID", Lang.getUUID());
		data.set("S_MTIME", tm);
		if (userInfo != null) { // 设置用户信息
			data.set("S_USER", userInfo.getCode()).set("S_CMPY", userInfo.getCmpyCode())
			.set("ILOG_IP", userInfo.getCurrentIpAddress());
		}
		sql = Context.getBuilder().insertByBean("SY_SERV_LOG_ITEM", data);
		params.add(data.getList(Constant.PARAM_PRE_VALUES));
	}
	if (sql != null) {
		Context.getExecutor().executeBatch(null, sql, params);
	}*/
}
